package com.jmp.autocofiguration.web.interceptor;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.jmp.autocofiguration.web.DefaultExceptionHandler;
import com.jmp.autocofiguration.web.ExceptionHandler;
import com.jmp.autocofiguration.web.WebMvcProperties;
import lombok.extern.slf4j.Slf4j;
import one.stand.exception.*;
import one.stand.service.user.CompanyPublicService;
import one.stand.service.user.TokenService;
import one.stand.util.RequestContext;
import one.stand.util.RequestContextHolder;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Objects;

/**
 * 授权判断
 * 判断条件{@link SecurityAuthCheck}注解
 * 判断信息从{@link RequestContext}上下文中获取
 * 异常处理{@link ExceptionHandler}，默认为{@link DefaultExceptionHandler}
 *
 * @author Administrator
 */
@Slf4j
public class SecurityAuthCheckInterceptor implements HandlerInterceptor {

    private ExceptionHandler exceptionHandler = new DefaultExceptionHandler();
    private WebMvcProperties webMvcProperties;
    private CompanyPublicService companyPublicService;
    private TokenService tokenService;

    public SecurityAuthCheckInterceptor(WebMvcProperties webMvcProperties, CompanyPublicService companyPublicService, TokenService tokenService) {
        this.companyPublicService = companyPublicService;
        this.webMvcProperties = webMvcProperties;
        this.tokenService = tokenService;
    }

    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
        try {

            if (o instanceof HandlerMethod) {
                HandlerMethod h = (HandlerMethod) o;
                SecurityAuthCheck securityAuthCheck = h.getMethodAnnotation(SecurityAuthCheck.class);

                if (Objects.nonNull(securityAuthCheck)) {
                    auth(securityAuthCheck);
                }
            }

            return true;
        } catch (Exception e) {
            exceptionHandler.handler(e, httpServletResponse);
            return false;
        }
    }

    private void auth(SecurityAuthCheck securityAuthCheck) throws Exception {
        //验证是否需要进行登陆校验
        RequestContext requestContext = RequestContextHolder.getRequestContext();
        if (log.isDebugEnabled()) {
            log.debug("request context:{}", JSON.toJSONString(requestContext));
        }

        if (!requestContext.isLogin()) {
            throw new LoginException("请登录");
        }

        if (webMvcProperties.isCheckCompanyKey()
                && StringUtils.isNoneBlank(requestContext.getUser().getCompanyKey())
                && !requestContext.getUser().getCompanyKey().equals(requestContext.getRequest().getCompanyKey())) {
            log.error("companyKey不同：{}--{}", requestContext.getUser().getCompanyKey(), requestContext.getRequest().getCompanyKey());
            throw new ParamException("登陆companyKey不同");
        }

        if (webMvcProperties.isCheckPhoneBind() && securityAuthCheck.checkPhone()
                && !companyPublicService.isPhoneBind(requestContext.getUser().getUserId())) {
            String token = requestContext.getRequest().getToken();
            if (StringUtils.isNoneBlank(token)) {
                tokenService.remove(Lists.newArrayList(Long.valueOf(requestContext.getUser().getUserId())));
            }
            throw new PhoneNotFoundException("请重新登录,绑定手机号");
        }

        RequestContext.User user = requestContext.getUser();
        if (securityAuthCheck.company() && (Objects.isNull(user.getCompanyId()) || user.getCompanyId() < 0)) {
            throw new CompanyException("请先创建企业,再进行操作");
        }

        if (securityAuthCheck.isBoss() && (Objects.isNull(user.getRoleId()) || user.getRoleId() <= 0)) {
            throw new BossException("不是Boss，不能进行此操作");
        }

        if (securityAuthCheck.card()) {
            if (Objects.isNull(user.getCardId())) {
                throw new CardException("名片不存在");
            }

            if (securityAuthCheck.status()) {
                if (!companyPublicService.isAudit(user.getCompanyId())) {
                    throw new CompanyException("您创建的企业正在审核中");
                }
            }

            if (webMvcProperties.isCheckCardTime()) {
                if (!companyPublicService.isEffective(user.getCompanyId())) {
                    throw new CardNumServiceException("名片已过期");
                }
            }
        }
    }
}
